import math
import pandas as pd
import backtrader as bt
from pyLibs import BacktraderUtits as btu


class PinBar(btu.BaseStrategy):
    def __init__(self):
        super(PinBar, self).__init__('single')
        for i, data in enumerate(self.datas):
            ema = bt.indicators.ExponentialMovingAverage(data, period=55)
            bollinger = bt.indicators.BollingerBands(data, period=20, devfactor=2.0)
            volume_ma = bt.indicators.SmoothedMovingAverage(data.volume, period=100)
            self.indicators[data._name]['ema'] = ema
            self.indicators[data._name]['boll_mid'] = bollinger.mid
            self.indicators[data._name]['pinbar'] = bt.talib.CDLHAMMER(data.open, data.high, data.low, data.close)
            self.condition[data._name]['is_short_short_trend'] = bt.And(ema > bollinger.mid, bollinger.mid > data.close)  # 是否短期多头趋势

    def next(self):
        for i, data in enumerate(self.datas):
            inds = self.indicators[data._name]
            cond = self.condition[data._name]
            index = len(self.watch[data._name])
            watchDict = {
                'datetime': data.datetime.datetime(0),
                'open': data.open[0],
                'close': data.close[0],
                'high': data.high[0],
                'low': data.low[0],
                'ema': inds['ema'][0],
                'boll_mid': inds['boll_mid'][0],
                'atr': inds['atr'][0],
                'platform_high': inds['hhv'][0],
                'platform_low': inds['llv'][0],
                'vol_release': cond['is_vol_release'][0],
                'vol_multiplier': cond['is_vol_multiplier'][0],
            }
            if index == 0 or self.watch[data._name].loc[index-1:, 'status'].values[0] in ['取消', '卖出']:
                if cond['is_short_short_trend'][0] and inds['pinbar'][0] > 0:
                    watchDict['morphology'] = 'PinBar'
                    watchDict['break_price'] = data.high[0]
                    watchDict['status'] = '关注'
                    self.watch[data._name].loc[index] = watchDict
            else:
                watchDict['morphology'] = self.watch[data._name].loc[index - 1:, 'morphology'].values[0]
                watchDict['break_price'] = self.watch[data._name].loc[index - 1:, 'break_price'].values[0]
                if self.watch[data._name].loc[index-1:, 'status'].values[0] == '关注':
                    if data.close[0] > self.watch[data._name].loc[index-1:, 'break_price'].values[0]:
                        watchDict['initial_loss'] = self.watch[data._name].loc[index-1:, 'platform_low'].values[0]
                        self.lossPrice[data._name] = self.watch[data._name].loc[index-1:, 'platform_low'].values[0]
                        self.buyPrice[data._name] = self.watch[data._name].loc[index-1:, 'close'].values[0]
                        watchDict['status'] = '买入'
                        symbol_multi = self.broker.getcommissioninfo(data).p.mult
                        total_value = self.broker.getvalue()
                        lots = math.floor(total_value / (symbol_multi * data.close[0]) / 100) * 100
                        self.buy_bracket(data, size=lots, stopprice=self.lossPrice[data._name])
                        self.log('买入 信号, 交易单价: %.2f, 交易数量: %i, 当前仓位: %i, 初始止损价：%.2f' %
                                 (data.close[0], lots, self.getposition(data).size, self.lossPrice[data._name]))
                    elif data.close[0] < self.watch[data._name].loc[index-1:, 'platform_low'].values[0]:
                        watchDict['status'] = '取消'
                    else:
                        watchDict['status'] = '关注'
                    self.watch[data._name].loc[index] = watchDict
                elif self.watch[data._name].loc[index-1:, 'status'].values[0] in ['买入', '持仓']:
                    watchDict['initial_loss'] = self.watch[data._name].loc[index - 1:, 'initial_loss'].values[0]
                    watchDict['moving_lost'] = self.watch[data._name].loc[index - 1:, 'moving_lost'].values[0]
                    if data.close[0] < self.lossPrice[data._name]:
                        watchDict['status'] = '卖出'
                        if self.close(data):
                            if self.lossPrice == self.watch[data._name].loc[index-1:, 'initial_loss'].values[0]:
                                self.log('初始止损 信号 (平仓), 交易单价: %.2f, 交易数量: %i' % (
                                    data.close[0], self.getposition(data).size))
                            else:
                                self.log('移动止盈 信号 (平仓), 交易单价: %.2f, 交易数量: %i' % (
                                    data.close[0], self.getposition(data).size))
                    else:
                        if data.close[0] > self.buyPrice[data._name] * 1.01:
                            watchDict['moving_lost'] = max([round((data.low[x] - inds['atr'][x] * 1.5), 3) for x in range(-8, 0)])
                            self.lossPrice[data._name] = watchDict['moving_lost']
                        watchDict['status'] = '持仓'
                    self.watch[data._name].loc[index] = watchDict